package analiseSintatica.Regras.Declaracoes;

import java.util.LinkedList;

import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.NoArvore;
import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.Regras.DeclaracoesIniciais.RegraDeclaracao;
import analiseSintatica.Regras.Tipos.RegraTipoPrimitivo;

/**
 *
 * @author Edney
 */
public class RegraDeclaracaoVar extends Regra {

    RegraAtribuicaoVar atribuicaovar = RegraAtribuicaoVar.getInstance();
    protected static Regra instancia;
    protected String estrutura = "<declaracao_var> ::= <tipo_primitivo> ( ['*'] identificador [<atribuicao_var>] | identificador [<array>] ){',' ( ['*'] identificador [<atribuicao_var>] | identificador <array> ) } ';'";

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraDeclaracaoVar() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraDeclaracaoVar getInstance() {
        if (instancia == null) {
            instancia = new RegraDeclaracaoVar();
        }
        return (RegraDeclaracaoVar) instancia;
    }

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

       // System.out.println("Entrei em declaracao var");
        ErroSintaticoException erros = new ErroSintaticoException();

        NoArvore naoterminaldeclaracaoVar = new NoArvore("<declaracaoVar>", false);

        try {

            naoterminaldeclaracaoVar.adicionaFilho(RegraTipoPrimitivo.getInstance().analisar(listaTokens));

        } catch (ErroSintaticoException e) {

            while (e.size() != 0) {
                erros.addErros(e.getErros());
            }

        }

        try {

            if (listaTokens.getFirst().getToken().equals("*")) {


                naoterminaldeclaracaoVar.adicionaFilho(reconheceToken(listaTokens, "*",estrutura));

                naoterminaldeclaracaoVar.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));

                if (RegraAtribuicaoVar.getInstance().getPrimeiro().contains(listaTokens.getFirst().getToken())) {

                    naoterminaldeclaracaoVar.adicionaFilho(RegraAtribuicaoVar.getInstance().analisar(listaTokens));

                }


            } else {
                
                naoterminaldeclaracaoVar.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));

                try {
                    if(RegraArray.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema()))
                    naoterminaldeclaracaoVar.adicionaFilho(RegraArray.getInstance().analisar(listaTokens));

                } catch (ErroSintaticoException e) {

                    while (e.size() != 0) {
                        erros.addErros(e.getErros());
                    }


                }

            }

        } catch (ErroSintaticoException e) {
            //fazer o erro
            //while(e.size() != 0)
            //erros.addErros(e.getErros());
        }

        while (listaTokens.getFirst().getToken().equals("delimitador") && listaTokens.getFirst().getLexema().equals(",")) {

            naoterminaldeclaracaoVar.adicionaFilho(reconheceLexema(listaTokens, "delimitador", ",",estrutura));

            try {

                if (listaTokens.getFirst().getToken().equals("*")) {


                    naoterminaldeclaracaoVar.adicionaFilho(reconheceToken(listaTokens, "*",estrutura));

                    naoterminaldeclaracaoVar.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));

                    if (RegraAtribuicaoVar.getInstance().getPrimeiro().contains(listaTokens.getFirst().getToken())) {

                        naoterminaldeclaracaoVar.adicionaFilho(RegraAtribuicaoVar.getInstance().analisar(listaTokens));

                    }


                } else {

                    naoterminaldeclaracaoVar.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));

                    try {

                        naoterminaldeclaracaoVar.adicionaFilho(RegraArray.getInstance().analisar(listaTokens));

                    } catch (ErroSintaticoException e) {

                        while (e.size() != 0) {
                            erros.addErros(e.getErros());
                        }

                    }

                }

            } catch (ErroSintaticoException e) {

                //fazer o erro
                //while(e.size() != 0)
                //erros.addErros(e.getErros());
            }

        }

      //  try {

            naoterminaldeclaracaoVar.adicionaFilho(reconheceLexema(listaTokens,"delimitador", ";",estrutura));

       /* } catch (ErroSintaticoException e) {
                while (e.size() != 0) {
                            erros.addErros(e.getErros());
                        }
        }*/
System.out.println("Terminei Declaracao var");

        return naoterminaldeclaracaoVar;
    }

    @Override
    protected void setPrimeiro() {

        this.primeiro.add("char");
        this.primeiro.add("int");
        this.primeiro.add("float");
        this.primeiro.add("boolean");


    }

    @Override
    protected void setSeguinte() {

                //s(decls_inicial) = "void" U p(decls_inicial)
        this.seguinte.add("void");
        this.primeiro.add("typedef");
        this.primeiro.add("const");
        this.primeiro.add("identificador");
        this.primeiro.add("char");
        this.primeiro.add("int");
        this.primeiro.add("float");
        this.primeiro.add("boolean");
    }
}
